package com.zhangke.websocket;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.zhangke.websocket.request.Request;
import com.zhangke.websocket.response.ErrorResponse;
import com.zhangke.websocket.util.LogUtil;

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 使用操作线程发送数据
 * <p>
 * Created by ZhangKe on 2019/3/29.
 */
public class WebSocketEngine {

    private static final String TAG = "WSWebSocketEngine";
    private  ExecutorService threadExecutor;

//    private OptionThread mOptionThread;

    WebSocketEngine() {
//        mOptionThread = new OptionThread();
//        mOptionThread.start();
        threadExecutor = Executors.newSingleThreadExecutor();
    }

    boolean sendRequest(WebSocketWrapper webSocket,
                     Request request,
                     SocketWrapperListener listener) {
//        if (mOptionThread.mHandler == null) {
        if (threadExecutor ==null || threadExecutor .isShutdown() || threadExecutor.isTerminated()  ) {
            listener.onSendDataError(request,
                    ErrorResponse.ERROR_UN_INIT,
                    null);
            LogUtil.e(TAG ,"sendRequest  1");

            return false;
        } else {
            ReRunnable runnable = ReRunnable.obtain();
            runnable.type = 0;
            runnable.request = request;
            runnable.webSocketWrapper = webSocket;
//            mOptionThread.mHandler.post(runnable);
            threadExecutor.execute(runnable);
            LogUtil.e(TAG ,"sendRequest  2");
            
            return true;
        }
    }

    void connect(WebSocketWrapper webSocket,
                 SocketWrapperListener listener) {

//        if (mOptionThread.mHandler == null) {
        if (threadExecutor ==null || threadExecutor .isShutdown() || threadExecutor.isTerminated()  ) {
            com.tao.utilslib.log.LogUtil.e(TAG , "WebSocketEngine not start!"   );
            listener.onConnectFailed(new Exception("WebSocketEngine not start!"));
        }else{
            ReRunnable runnable = ReRunnable.obtain();
            runnable.type = 1;
            runnable.webSocketWrapper = webSocket;
            com.tao.utilslib.log.LogUtil.e(TAG , " connect  ReRunnable " +runnable + "   " +webSocket);
            threadExecutor.execute(runnable);
        }
    }

    void disConnect(WebSocketWrapper webSocket,
                    SocketWrapperListener listener) {
//        if (mOptionThread.mHandler != null) {
            if (threadExecutor ==null || threadExecutor .isShutdown() || threadExecutor.isTerminated()  ) {

                ReRunnable runnable = ReRunnable.obtain();
            runnable.type = 2;
            runnable.webSocketWrapper = webSocket;
//            mOptionThread.mHandler.post(runnable);
                threadExecutor.execute(runnable);
                
            }else{
            LogUtil.e(TAG, "WebSocketEngine not start!");
        }
    }

    void destroyWebSocket(WebSocketWrapper webSocket){
        
        com.tao.utilslib.log.LogUtil.e(TAG , " destroyWebSocket " +webSocket);

//        if (mOptionThread.mHandler != null) {
        if (threadExecutor ==null || threadExecutor .isShutdown() || threadExecutor.isTerminated()  ) {

            ReRunnable runnable = ReRunnable.obtain();
        
            runnable.type = 3;
            runnable.webSocketWrapper = webSocket;
//            mOptionThread.mHandler.post(runnable);
            threadExecutor.execute(runnable);

        }else{
            LogUtil.e(TAG, "WebSocketEngine not start!");
        }
    }

    public void destroy() {
        if (threadExecutor ==null || threadExecutor .isShutdown() || threadExecutor.isTerminated()  ) {
            return;
            
            
        }
        threadExecutor.shutdownNow();
        threadExecutor =null;
//        if (threadExecutor != null) {
//            
//            if (mOptionThread.mHandler != null) {
//                mOptionThread.mHandler.sendEmptyMessage(OptionHandler.QUIT);
//            }
//        }
    }

    private class OptionThread extends Thread {

        private OptionHandler mHandler;

        @Override
        public void run() {
            super.run();
            try {
                Looper.prepare();
                mHandler = new OptionHandler();
                Looper.loop();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                com.tao.utilslib.log.LogUtil.e(TAG ,"handler_finally");
            }
        }
    }

    private static class OptionHandler extends Handler {

        private static final int QUIT = 1;

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    }

    private static class ReRunnable implements Runnable {

        private static Queue<ReRunnable> POOL = new ArrayDeque<>(10);

        static ReRunnable obtain() {
//            ReRunnable runnable = POOL.poll();
//            if (runnable == null) {
//                runnable = new ReRunnable();
//            }
            return new ReRunnable();
        }

        /**
         * 0-发送数据；
         * 1-连接；
         * 2-断开连接；
         * 3-销毁 WebSocketWrapper 对象。
         */
        private int type;
        private WebSocketWrapper webSocketWrapper;
        private Request request;

        @Override
        public void run() {
            try {
                LogUtil.e(TAG ,this+" ReRunnable  " + webSocketWrapper +"  " +request +"  " +type+"  "+ Thread.currentThread());

                if (webSocketWrapper == null) {
                    return;
                }
                if (type == 0 && request == null) return;
                if (type == 0) {
                    webSocketWrapper.send(request);
                } else if (type == 1) {
                    webSocketWrapper.reconnect();
                } else if (type == 2) {
                    webSocketWrapper.disConnect();
                }else if(type == 3){
                    webSocketWrapper.destroy();
                }
            } catch (Exception e){
                e.printStackTrace();
            }
            finally {
                webSocketWrapper = null;
                request = null;
                release();
                com.tao.utilslib.log.LogUtil.e(TAG ," run over " +this);
            }
        }

        void release() {
            POOL.offer(this);
        }
    }
}
